package org.jeecg.chase.common.supper.process;

import org.apache.commons.lang.StringUtils;
import org.jeecg.chase.common.base.annotation.Process;
import org.jeecg.chase.common.base.annotation.assist.MethodAssist;
import org.jeecg.chase.common.utils.InvokeSupportUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author leikai
 * @version 1.0
 * @description:
 * @date 2021/08/04/0004 17:45
 */
public class CommonProcessBuilder {

    private static Logger log = LoggerFactory.getLogger(CommonProcessBuilder.class);

    private static List<CommonProcess> commonProcessList = new ArrayList<CommonProcess>();


    public static CommonProcess changeToCommonProcess(Process process) {
        CommonProcess commonProcess = new CommonProcess();
        commonProcess.setConditionExpression(process.conditionExpression());
        commonProcess.setService(process.service());
        commonProcess.setMethod(process.method());
        commonProcessList.add(commonProcess);
        return commonProcess;
    }

    public static List<CommonProcess> changeToCommonProcessList(Process[] processArray) {
        List<CommonProcess> processList = new ArrayList<CommonProcess>();
        for (Process process : processArray) {
            CommonProcess commonProcess = changeToCommonProcess(process);
            processList.add(commonProcess);
        }
        return processList;
    }

    public static void buidCommonProcess(ApplicationContext appCtx) {
        for (CommonProcess commonProcess : commonProcessList) {
            try {
                buidCommonProcess(appCtx, commonProcess);
            } catch (Exception e) {
                log.info("警告！！！！！！！！！！！！！！！！！！！！！！" + e.getMessage());
            }
        }
    }

    public static void buidCommonProcess(ApplicationContext appCtx, CommonProcess commonProcess) {
        //脚本的service
        buildServiceObject(appCtx, commonProcess);

        //脚本的method
        String methodStr = commonProcess.getMethod();
        MethodAssist methodAssist = getMethodAssist(methodStr);

        buildMethodObject(methodAssist.getMethodName(), commonProcess);

        //构建脚本的参数
        buidParamList(methodAssist.getParam(), commonProcess);
    }

    private static void buildServiceObject(ApplicationContext appCtx, CommonProcess commonProcess) {
        Object serviceObject = null;
        String serviceName = commonProcess.getService();
        try {
            serviceObject = appCtx.getBean(serviceName);
        } catch (Exception e) {
            throw new RuntimeException("的Processes中的" + serviceName + "不存在", e);
        }
        commonProcess.setServiceObject(serviceObject);
    }

    private static MethodAssist getMethodAssist(String methodStr) {
        MethodAssist methodAssist = new MethodAssist();
        Integer beginIndex = methodStr.indexOf('(');
        Integer endIndex = methodStr.indexOf(')');
        String param = methodStr.substring(beginIndex + 1, endIndex);
        String methodName = methodStr.substring(0, beginIndex);
        methodAssist.setMethodName(methodName);
        methodAssist.setParam(param);
        return methodAssist;
    }

    private static void buildMethodObject(String methodName, CommonProcess commonProcess) {
        //脚本的service
        Object serviceObject = commonProcess.getServiceObject();
        Method method = InvokeSupportUtils.getMethod(serviceObject.getClass(), methodName);
        if (null == method) {
            throw new RuntimeException("的Processes中的" + commonProcess.getService() + "." + methodName + "不存在");
        }
        commonProcess.setMethod(methodName);
        commonProcess.setMethodObject(method);
    }

    private static void buidParamList(String param, CommonProcess commonProcess) {
        Method method = commonProcess.getMethodObject();
        Class<?>[] paramTypes = method.getParameterTypes();
        commonProcess.setParamTypes(paramTypes);

        //脚本的第一个参数是否是集合型
        if (paramTypes.length > 0) {
            Boolean firstParamTypeIsIterable = Iterable.class.isAssignableFrom(paramTypes[0]);
            commonProcess.setFirstParamTypeIsIterable(firstParamTypeIsIterable);
        }

        //脚本的最后一个参数是否是可变参数（数组）
        Boolean lastParamTypeIsArray = false;
        if (paramTypes.length > 1) {
            Class<?> lastParamType = paramTypes[paramTypes.length - 1];
            lastParamTypeIsArray = lastParamType.isArray();
        }

        List<Object> paramList = new ArrayList<Object>();
        if (StringUtils.isNotBlank(param)) {
            String[] paramStrArray = param.split(",");
            if (lastParamTypeIsArray == true) {
                Integer i = 0;
                for (i = 0; i < paramTypes.length - 2; i++) {
                    addParam(paramList, paramStrArray[i]);
                }
                List<Object> lastParamList = new ArrayList<Object>();
                for (int j = i; j < paramStrArray.length; j++) {
                    addParam(lastParamList, paramStrArray[j]);
                }
                String[] lastParam = new String[lastParamList.size()];
                lastParam = lastParamList.toArray(lastParam);
                paramList.add(lastParam);

            } else {
                for (String paramStr : paramStrArray) {
                    addParam(paramList, paramStr);
                }
            }
        }
        commonProcess.setParamList(paramList);
    }

    private static void addParam(List<Object> paramList, String param) {
        if ("null".equals(param)) {
            paramList.add(null);
        } else {

            paramList.add(param.trim());
        }
    }
}
